package me.twoday.library.mine.common.parser;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

import me.twoday.library.mine.adapter.WithTitleBarListAdapter;
import net.htmlparser.jericho.Source;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * HTML문서의 파싱을 돕는 헨들러 클래스
 * [Internet 퍼미션 꼭 추가해 주자!!!!!]
 *
 * @author 김학성
 * @since 2012. 5. 19.
 */
@SuppressWarnings("unused")
public abstract class JerichoHandler<T> 
{
	private static final String TAG = "JerichoHandler";
	protected URL mUrl;
	protected Handler mHandler;
	protected ProgressDialog mPdLoading;
	protected String mCharSet;
	protected InputStream mInputStream;
	protected Source mSource;
	protected ArrayList<T> mDataList;
	protected Activity mParentActivity;
	protected Context mParentContext;
	protected WithTitleBarListAdapter mWithTitleBarAdapter;
	
	
	public JerichoHandler(Activity activity, String url, String charSet)
	{
		mParentActivity = activity;
		mParentContext = activity.getApplicationContext();
		mCharSet = charSet;
		getFullSourceParse(url);
		SetDataList();
	}
	
	/**
	 * 실제로 파싱할 문서의 Syntax를 정의한다. 
	 * 
	 * @param _source 풀파싱 해온 쌩 소스 
	 * @return ArrayList<T> 최종적으로 파싱한 리스트
	 */
	protected abstract ArrayList<T> parseSyntax(Source _source);
	
	/**
	 * 실제로 데이터를 보여줄 Syntax를 정의한다.
	 * 
	 * @param activity 엑티비티 
	 * @param _dataList 파싱결과 dataList
	 */
	protected abstract void listSyntax(Activity activity, ArrayList<T> _dataList);
	
	/**
	 * 파싱할 주소를 셋팅하고 
	 * 
	 *  @param url 파싱할 주소 
	 *  @param charSet 캐릭터셋 
	 *  @return mSource 파싱된 풀소스 
	 */
	protected void getFullSourceParse(String url)
	{
		mSource = null;
		
		try {
			mUrl = new URL(url);
		} catch (MalformedURLException e) {
			Log.i("Debuging", "URL Make Error : "+ mUrl);
			e.printStackTrace();
		}
		
	    try 
	    {
	    	mInputStream = mUrl.openStream();
		}
	    catch (IOException e1) 
	    {
			Log.i(TAG, "InputStream Make Error : "+ e1.toString());
			e1.printStackTrace();
		}
	   
	    try 
	    {
			mSource = new Source(new InputStreamReader(mInputStream, mCharSet));
		}
	    catch (UnsupportedEncodingException e) 
		{
			Log.i(TAG, "InputStreamReader Encoding Error : "+ mSource);
			e.printStackTrace();
		}
	    catch (IOException e) 
		{
			Log.i(TAG, "InputStream Make Error : "+ mSource);
			e.printStackTrace();
		}
	    
	    // 셋팅된 정보로 파싱을 시작한다. 
	    mSource.fullSequentialParse();
	}
	
	/**
	 * 실제적으로 파싱 데이터가 셋팅되는 부분
	 * 파싱이 완료됬을 경우 셋팅이 진행되도록 구현 
	 * 
	 */
	@SuppressWarnings("unchecked")
	public void SetDataList() 
	{
		mHandler = new Handler() 
		{
			public void handleMessage(Message msg) 
	        {
	    		mPdLoading.dismiss();
	    		mDataList = (ArrayList<T>)msg.obj;   		
	    		int mDataListSize = mDataList.size();
	    		
	    		// 파싱된 데이터를 어떻게 보여줄지 정의한다. 
	    		listSyntax(mParentActivity, mDataList);
	        }
	    };
	    mPdLoading = startTask(mParentActivity, mHandler);
	}
	
	/**
	 * 외부의 대이터를 다운 받는 시간동안 '로딩중'을 구현하기 위한 함수 
	 * 
	 * @param activity 로딩을 위해 넘기는 activity
	 * @param handler 또한 로딩을 헨들링 하기위해.
	 * @return SetDataList에서 사용할 progressDialog
	 */
	public ProgressDialog startTask(Activity activity, Handler handler)
	{
		ProgressDialog progressDialog = ProgressDialog.show(activity, "", "로딩중입니다.조금만 기다려주세요:)", true, false);
		//Log.i("debug1", progressDialog +"");
		final Message msg = Message.obtain();
		
		Thread thread = new Thread(new Runnable() 
		{
			@Override
			public void run() 
			{
				// parseSyntax에서 실제로 어떻게 파싱할지 로직을 넣는다.
				msg.obj = parseSyntax(mSource);
				mHandler.sendMessage(msg);
			}	
		});
		thread.start();
		return progressDialog;
	}
}
